Imports MirEvo.Keyboard

Namespace GameWindow

    Module mGameWindow

        'DRAWING AREA
        Public Const DrawAreaCentreX As Single = 0.5
        Public Const DrawAreaCentreY As Single = 0.25
        Public Const DrawAreaFactorX As Single = 1.1
        Public Const DrawAreaFactorY As Single = 2.5
        Public DrawAreaStartOffsetX As Integer, DrawAreaStartOffsetY As Integer
        Public DrawAreaTilesX As Integer, DrawAreaTilesY As Integer
        Public DrawCentreTileX As Integer, DrawCentreTileY As Integer

        'MOVEMENT OFFSET
        Public MovementOffsetX As Double, MovementOffsetY As Double

        'DrawOffset             
        Dim offsetX As Integer
        Dim offsetY As Integer

        'CENTRE COORDS
        Public CoordX As Integer, CoordY As Integer

        'Mouse
        Private pointerdirection As EvoLib.Protocol.Direction
        Public MouseX As Integer, MouseY As Integer
        Public MousePointX As Integer, MousePointY As Integer

        Public WithEvents GameWin As GUI.MirWindow
        Public WithEvents Tooltip As GUI.MirText
        Public tooltipid As Int64
        Private bShowTooltip As Boolean

        Public mCurrentMap As cMirMapFile
        Public mCurrentMapFile As String
        Public mCurrentMapName As String

        Public MouseAngle As Double

        Public isShiftDown As Boolean
        Public isControlDown As Boolean
        Public isAltDown As Boolean

        Public MouseOverMob As Boolean
        Public MouseOverActor As Actor.MirActor

        Public Sub Init()

            CalculateDrawingArea()

            GameWin = New GUI.MirWindow("GameWin", 0, 0, Constants.gGameResX, Constants.gGameResY)

            Dim cols As New ArrayList
            cols.Add(Color.White)
            cols.Add(Color.Gray)
            cols.Add(Color.LimeGreen)
            cols.Add(Color.Orchid)
            cols.Add(Color.LightGray)
            cols.Add(Color.SkyBlue)
            cols.Add(Color.Magenta)

            Tooltip = New GUI.MirText(GameWin, "Tooltip", 0, 0, DirectX.ProFont9, "", Color.FromArgb(128, 128, 128, 128), Color.Gold, cols, 3, 3)
            Tooltip.Visible = False

            Windows.AddWindow(GameWin, Windows.WindowType.AlwaysBottom)

            'myPlayer.QueueAnim(EvoLib.Protocol.HUMAnimation.Standing, EvoLib.Protocol.Direction.S)

        End Sub

        Public Sub Shutdown()

            GameWin.Destory()
            Characters.ClearList()

        End Sub

        Public Sub LoadMap(ByRef map As String)

            mCurrentMapFile = map

            mCurrentMap = New cMirMapFile(map)

            'Characters.SetMapSize(mCurrentMap.mWidth, mCurrentMap.mHeight)
            Mobs.Reset()
            FloorItems.Reset()
            Characters.ClearList()
            NPCs.ClearList()

            Globals.IsLoadingTiles = True
            MessageBoxes.SetStateNotice("Loading map...")

        End Sub

        Public Sub DrawTooltip(ByRef mode As Globals.DrawingMode)

            If bShowTooltip Then

                Tooltip.Visible = True
                Tooltip.Draw(mode, 0, 0, 0.02F)
                Tooltip.Visible = False

            End If

        End Sub

        Public Sub HideTooltip()
            bShowTooltip = False
            tooltipid = 0
        End Sub

        Public Sub SetTooltip(ByRef textstr As String, ByRef itemid As Int64, Optional OffsetYByHeight As Boolean = False)

            Tooltip.TextString = textstr

            SetupToolTipPos(OffsetYByHeight)

            tooltipid = itemid
            bShowTooltip = True

        End Sub

        Public Sub SetupToolTipPos(Optional OffsetYByHeight As Boolean = False)

            Dim x As Integer = Mouse.XCoord + Constants.TooltipXOffset
            Dim y As Integer = Mouse.YCoord + Constants.TooltipYOffset

            If OffsetYByHeight Then y = y - Tooltip.Height

            If x + Tooltip.Width > Constants.gGameResX Then x = Constants.gGameResX - Tooltip.Width
            If y + Tooltip.Height > Constants.gGameResY Then y = Constants.gGameResY - Tooltip.Height
            If x < 0 Then x = 0
            If y < 0 Then y = 0

            Tooltip.SetPos(x, y)

        End Sub

        Public Sub SetItemTooltip(ByRef item As EvoLib.Protocol.ItemInfo)

            If tooltipid <> item.INT_ID Then

                Dim tmp As String = "\b"

                Select Case item.Base.BYTE_ITEMCLASS

                    Case EvoLib.Protocol.ItemClass.Loot
                        tmp &= "\1"
                    Case EvoLib.Protocol.ItemClass.Normal
                        tmp &= "\0"
                    Case EvoLib.Protocol.ItemClass.Superior
                        tmp &= "\2"
                    Case EvoLib.Protocol.ItemClass.Rare
                        tmp &= "\3"

                End Select

                tmp &= item.Base.STR_NAME & "\b"

                If item.AddedStats.INT2_MIN_AC + item.AddedStats.INT2_MAX_AC <> 0 Then
                    tmp &= "\n\4AC: \0" & (item.Base.Stats.INT2_MIN_AC + item.AddedStats.INT2_MIN_AC) & "-" & (item.Base.Stats.INT2_MAX_AC + item.AddedStats.INT2_MAX_AC) & " \5(" & item.AddedStats.INT2_MIN_AC & "-" & item.AddedStats.INT2_MAX_AC & ")"
                ElseIf item.Base.Stats.INT2_MIN_AC + item.Base.Stats.INT2_MAX_AC Then
                    tmp &= "\n\4AC: \0" & (item.Base.Stats.INT2_MIN_AC) & "-" & (item.Base.Stats.INT2_MAX_AC)
                End If

                If item.AddedStats.INT2_MIN_MAC + item.AddedStats.INT2_MAX_MAC <> 0 Then
                    tmp &= "\n\4MAC: \0" & (item.Base.Stats.INT2_MIN_MAC + item.AddedStats.INT2_MIN_MAC) & "-" & (item.Base.Stats.INT2_MAX_MAC + item.AddedStats.INT2_MAX_MAC) & " \5(" & item.AddedStats.INT2_MIN_MAC & "-" & item.AddedStats.INT2_MAX_MAC & ")"
                ElseIf item.Base.Stats.INT2_MIN_MAC + item.Base.Stats.INT2_MAX_MAC Then
                    tmp &= "\n\4MAC: \0" & (item.Base.Stats.INT2_MIN_MAC) & "-" & (item.Base.Stats.INT2_MAX_MAC)
                End If

                If item.AddedStats.INT2_MIN_DC + item.AddedStats.INT2_MAX_DC <> 0 Then
                    tmp &= "\n\4DC: \0" & (item.Base.Stats.INT2_MIN_DC + item.AddedStats.INT2_MIN_DC) & "-" & (item.Base.Stats.INT2_MAX_DC + item.AddedStats.INT2_MAX_DC) & " \5(" & item.AddedStats.INT2_MIN_DC & "-" & item.AddedStats.INT2_MAX_DC & ")"
                ElseIf item.Base.Stats.INT2_MIN_DC + item.Base.Stats.INT2_MAX_DC Then
                    tmp &= "\n\4DC: \0" & (item.Base.Stats.INT2_MIN_DC) & "-" & (item.Base.Stats.INT2_MAX_DC)
                End If

                If item.AddedStats.INT2_MIN_SC + item.AddedStats.INT2_MAX_SC <> 0 Then
                    tmp &= "\n\4SC: \0" & (item.Base.Stats.INT2_MIN_SC + item.AddedStats.INT2_MIN_SC) & "-" & (item.Base.Stats.INT2_MAX_SC + item.AddedStats.INT2_MAX_SC) & " \5(" & item.AddedStats.INT2_MIN_SC & "-" & item.AddedStats.INT2_MAX_SC & ")"
                ElseIf item.Base.Stats.INT2_MIN_SC + item.Base.Stats.INT2_MAX_SC Then
                    tmp &= "\n\4SC: \0" & (item.Base.Stats.INT2_MIN_SC) & "-" & (item.Base.Stats.INT2_MAX_SC)
                End If

                If item.AddedStats.INT2_MIN_MC + item.AddedStats.INT2_MAX_MC <> 0 Then
                    tmp &= "\n\4MC: \0" & (item.Base.Stats.INT2_MIN_MC + item.AddedStats.INT2_MIN_MC) & "-" & (item.Base.Stats.INT2_MAX_MC + item.AddedStats.INT2_MAX_MC) & " \5(" & item.AddedStats.INT2_MIN_MC & "-" & item.AddedStats.INT2_MAX_MC & ")"
                ElseIf item.Base.Stats.INT2_MIN_MC + item.Base.Stats.INT2_MAX_MC Then
                    tmp &= "\n\4MC: \0" & (item.Base.Stats.INT2_MIN_MC) & "-" & (item.Base.Stats.INT2_MAX_MC)
                End If

                If item.AddedStats.INT_MAX_DURABILITY <> 0 Then
                    If item.INT_DURABILITY = 0 Then
                        tmp &= "\n\4Dura: \6" & Int(item.INT_DURABILITY / 1000) & "\0\\" & (item.AddedStats.INT_MAX_DURABILITY + item.Base.Stats.INT_MAX_DURABILITY) & " \5(+" & item.AddedStats.INT_MAX_DURABILITY & ")"
                    Else
                        tmp &= "\n\4Dura: \0" & Int(item.INT_DURABILITY / 1000) & "\\" & (item.AddedStats.INT_MAX_DURABILITY + item.Base.Stats.INT_MAX_DURABILITY) & " \5(+" & item.AddedStats.INT_MAX_DURABILITY & ")"
                    End If
                ElseIf item.Base.Stats.INT_MAX_DURABILITY <> 0 Then
                    If item.INT_DURABILITY = 0 Then
                        tmp &= "\n\4Dura: \6" & Int(item.INT_DURABILITY / 1000) & "\0\\" & item.Base.Stats.INT_MAX_DURABILITY
                    Else
                        tmp &= "\n\4Dura: \0" & Int(item.INT_DURABILITY / 1000) & "\\" & item.Base.Stats.INT_MAX_DURABILITY
                    End If
                End If

                If item.Base.INT2_LEVELREQ > 0 Then
                    If item.Base.INT2_LEVELREQ <= Player.PlayerLevel Then
                        tmp &= "\n\2Requires: Level " & item.Base.INT2_LEVELREQ
                    Else
                        tmp &= "\n\6Requires: Level " & item.Base.INT2_LEVELREQ
                    End If
                End If

                Select Case item.Base.BYTE_TYPE

                    Case ItemType.WarriorBook
                        If Player.PlayerJob = CharacterJobs.Warrior Then
                            tmp &= "\n\2Requires: Warrior"
                        Else
                            tmp &= "\n\6Requires: Warrior"
                        End If

                    Case ItemType.TaoistBook
                        If Player.PlayerJob = CharacterJobs.Taoist Then
                            tmp &= "\n\2Requires: Taoist"
                        Else
                            tmp &= "\n\6Requires: Taoist"
                        End If

                    Case ItemType.SorcererBook
                        If Player.PlayerJob = CharacterJobs.Sorcerer Then
                            tmp &= "\n\2Requires: Sorcerer"
                        Else
                            tmp &= "\n\6Requires: Sorcerer"
                        End If

                End Select

                'TODO: complete item tooltip

                SetTooltip(tmp, item.INT_ID)

            Else

                SetupToolTipPos()

            End If

        End Sub

        Public Sub CalculateDrawingArea()

            Dim w As Integer, h As Integer

            w = Constants.gGameResX * DrawAreaFactorX
            h = Constants.gGameResY * DrawAreaFactorY

            Dim r As Integer
            DrawAreaTilesX = Math.DivRem(w, Constants.TileWidth, r)
            If r = 0 Then DrawAreaTilesX += 1
            DrawAreaTilesY = Math.DivRem(h, Constants.TileHeight, r)
            If r = 0 Then DrawAreaTilesY += 1

            'Make sure there is an odd number of tiles in each dimension so we get a centre tile for the player
            Math.DivRem(DrawAreaTilesX, 2, r)
            If r = 0 Then DrawAreaTilesX += 1
            Math.DivRem(DrawAreaTilesY, 2, r)
            If r = 0 Then DrawAreaTilesY += 1

            Dim cx As Integer = (Constants.gGameResX / 2) - (Constants.TileWidth / 2)
            Dim cy As Integer = (Constants.gGameResY / 2) - (Constants.TileHeight / 2)

            DrawCentreTileX = DrawAreaTilesX * DrawAreaCentreX
            DrawCentreTileY = DrawAreaTilesY * DrawAreaCentreY

            'DrawAreaStartOffsetX = cx - ((DrawAreaTilesX \ 2) * Constants.TileWidth) - Constants.TileWidth
            'DrawAreaStartOffsetY = cy - ((DrawAreaTilesY \ 2) * Constants.TileHeight) - Constants.TileHeight
            DrawAreaStartOffsetX = cx - ((DrawCentreTileX) * Constants.TileWidth) '- Constants.TileWidth
            DrawAreaStartOffsetY = cy - ((DrawCentreTileY) * Constants.TileHeight) '- Constants.TileHeight

        End Sub

        Public Structure MapTile
            Dim TileSet As Byte
            Dim Idx As UInt16
        End Structure

        Public MDrawnMapTiles As List(Of MapTile) = New List(Of MapTile)

        Public Function HasDrawnTile(tileSet As Byte, index As UInt16) As Boolean

            For Each T As MapTile In mDrawnMapTiles

                If T.TileSet = tileSet Then
                    If T.Idx = Index Then
                        Return True
                    End If
                End If

            Next

            Return False

        End Function

        Private Sub GameWin_DrawWindow(ByRef mode As Globals.DrawingMode, ByRef x As Integer, ByRef y As Integer, ByRef z As Single) Handles GameWin.DrawWindow

            'flags to show: IsLoadingTiles: Denotes if tiles have started to load yet
            '               IsInGame: Denotes if we have waited already to load first scene tiles

            If Globals.IsLoadingTiles And Not Globals.IsInGame Then

                'wait for worker threads to load tiles
                System.Threading.Thread.Sleep(3000)
                'Remove map loading message
                MessageBoxes.RemoveStateNotice()

                'set IsInGame flag
                Globals.IsInGame = True

            End If

            If mode = Globals.DrawingMode.Overlay Then

                '===[Player Drawing]===
                'Draws the player onto an off screen Texture/Surface

                'Setup the render target for drawing the player
                DirectX.D3D.SetRenderTarget(0, DirectX.PlayerSurface)
                'Begin D3D scene
                DirectX.D3D.BeginScene()
                'Clear target and z-buffer
                DirectX.D3D.Clear(Microsoft.DirectX.Direct3D.ClearFlags.Target Or Microsoft.DirectX.Direct3D.ClearFlags.ZBuffer, Color.Transparent, 1.0F, 0)


                'Begin GameSprite rendering
                DirectX.GameSprite.Begin(Microsoft.DirectX.Direct3D.SpriteFlags.AlphaBlend)
                'Set draw mode to plain
                Engine.SetDrawModeNormal(1.0, Color.White)

                'Draw the player... in normal mode
                Player.DrawPlayer(Globals.DrawingMode.Normal)

                'End GameSprite rendering
                DirectX.GameSprite.End()

                'Set draw mode to tinted, ready to draw Alpha channels
                Engine.SetDrawModeTinted(1.0, Color.White)
                'Draw any tinted sections of the player
                Player.DrawPlayer(Globals.DrawingMode.Tinted)


                'End the D3D scene
                DirectX.D3D.EndScene()

                GameWindow.DrawLightsOverlay()

            End If

            'Start Coords for drawing the tile grid (top left of render area)
            offsetX = DrawAreaStartOffsetX + CInt(MovementOffsetX)
            offsetY = DrawAreaStartOffsetY + CInt(MovementOffsetY)

            'calculate (top-left) start tile coords
            Dim starttilex As Integer = CoordX - DrawCentreTileX
            Dim starttiley As Integer = CoordY - DrawCentreTileY

            'Make sure we have initially loaded some tiles first
            If Globals.IsInGame Then

                If mode = Globals.DrawingMode.Overlay Then
                    'Draw the floor Items onto their respective Overlay
                    FloorItems.Draw(mode, offsetX, offsetY, starttilex, starttiley, 0.23F)
                End If

            End If

            'Temporary Tiles
            Static tmps As SmallTile
            Static tmpl As LargeTile

            'Pixel Coords
            Static pos_X As Integer, pos_Y As Integer

            'Tile Coords
            Static Tile_Coord_X As Integer
            Static Tile_Coord_Y As Integer

            Static tmpOffsetY As Integer 'temnporary Y offset, for lining up tall Bottom_Small_Tile map objects

            'holds the present Z value for what is being Drawn
            Dim tmpZ As Single
            tmpZ = 0.99F

            'Clock Ticks
            Dim tc As Long = Date.Now.Ticks
            ' temp variable for remainders, to determine if Tile Coords are even numbers, so as to match Large_Tiles
            Dim r As Integer

            If mode = Globals.DrawingMode.Normal Then

                mDrawnMapTiles.Clear()

                'Set present Y-Pixel-Coord to Top of render-tiles-grid
                pos_Y = offsetY
                'set Current Y-Tile-Coord to its starting value
                Tile_Coord_Y = starttiley

                'Determine if this is an odd numbered tile...
                Math.DivRem(Tile_Coord_Y, 2, r)
                If r = 1 Then
                    'a remainder of 1 means an odd numbered tile
                    'add 1 tile height to the present Y-Pixel-Coord
                    pos_Y += Constants.TileHeight
                    'Add 1 to current Y-Tile-Coord
                    Tile_Coord_Y += 1
                End If

                'Step tileY coord from top to bottom of drawing area, stepping 2 at a time
                For tileY As Integer = 0 To DrawAreaTilesY Step 2
                    'for every increase in Y coordinate, add a little to the Z value
                    'this orders the scene correctly
                    tmpZ -= 0.02
                    'Set present X-Pixel-Coord to far left of render-tiles-grid
                    pos_X = offsetX
                    'set Current X-Tile-Coord to its start value
                    Tile_Coord_X = starttilex
                    'Determine if this is an odd numbered tile
                    Math.DivRem(Tile_Coord_X, 2, r)
                    If r = 1 Then
                        'a remainder of 1 means an odd numbered tile
                        'add 1 measure of TileWidth to the present X-Pixel-Coords
                        pos_X += Constants.TileWidth
                        'add 1 to current X-Tile-Coord
                        Tile_Coord_X += 1
                    End If

                    'step through tile indexes, step 2 at a time
                    For tileX As Integer = 0 To DrawAreaTilesX Step 2

                        'load Large Tile in temp variable
                        tmpl = mCurrentMap.GetLargeTile(Tile_Coord_X, Tile_Coord_Y)

                        'if TileSet is not Invalid
                        If tmpl.TileSet <> 255 Then
                            'temp MirImage for this tile
                            Dim tmpimg As MirImage = Libs.GetLib(GetImgLib(tmpl.TileSet)).Image(tmpl.Index, , True)
                            'check if MirImage is a valid object
                            If Not tmpimg Is Nothing Then

                                'use the MirImage for referenced by this Large tile
                                With tmpimg

                                    'Draw the large tile to screen, all large tiles draw with a Z-Order of 0.99F
                                    If Not Globals.IsLoadingTiles Then
                                        .Draw(pos_X, pos_Y, 0.99F)
                                        Dim tmpTile As MapTile
                                        tmpTile.TileSet = tmpl.TileSet
                                        tmpTile.Idx = tmpl.Index
                                        'If Tile_Coord_X = CoordX And Tile_Coord_Y = CoordY Then
                                        MDrawnMapTiles.Add(tmpTile)
                                        'End If

                                    End If

                                End With

                            End If

                        End If

                        'Add 2xTileWidth to the X-Pixel-Coords
                        pos_X += (Constants.TileWidth * 2)
                        'Add 2 to the X-Tile-Coord
                        Tile_Coord_X += 2

                    Next

                    'Add 2xTileHeight to the Y-Pixel-Coords
                    pos_Y += (Constants.TileHeight * 2)
                    'Add 2 to the Y-Tile-Coord
                    Tile_Coord_Y += 2
                Next

            End If

            'Reset the Z-Order to 0.99F
            tmpZ = 0.99F

            If mode = Globals.DrawingMode.Normal Or mode = Globals.DrawingMode.Shadow Or mode = Globals.DrawingMode.Text Then

                'reset Y-Pixel-Coord to far top of render area
                pos_Y = offsetY
                'reset Y-Tile-Coord to far top of render area
                Tile_Coord_Y = starttiley

                'iterate through each Y-Tile-Index
                For tileY As Integer = 0 To DrawAreaTilesY

                    'Decrease the Z-Order by 0.01F
                    tmpZ -= 0.005F
                    'reset X-Pixel-Coord to far left of render area
                    pos_X = offsetX
                    'also reset X-Tile-Coord to far left of render area
                    Tile_Coord_X = starttilex

                    'iterate through each X-Tile-Index
                    For tileX As Integer = 0 To DrawAreaTilesX

                        If mode = Globals.DrawingMode.Normal Then

                            'Drawing Of BottomTiles
                            'get small tile desc into temp variable
                            tmps = mCurrentMap.GetTile(Tile_Coord_X, Tile_Coord_Y)

                            'if bottom-tileset is valid
                            If tmps.BottomTileSet <> 255 Then
                                'if bottom-tileindex is valid
                                If tmps.BottomTileIndex <> 65535 Then
                                    'temp MirImage for this tile
                                    Dim tmpimg As MirImage = Libs.GetLib(GetImgLib(tmps.BottomTileSet)).Image(tmps.BottomTileIndex, , True)
                                    'check the temporary image is NOT an empty object (Is Nothing)
                                    If Not tmpimg Is Nothing Then
                                        'Use temporary MirImage
                                        With tmpimg

                                            'Work out the Y Offset
                                            tmpOffsetY = .Header.Height - Constants.TileHeight
                                            'Draw the Bottom Object Tile
                                            If Not Globals.IsLoadingTiles Then
                                                .Draw(pos_X, pos_Y - tmpOffsetY, tmpZ)
                                                Dim tmpBTile As MapTile
                                                tmpBTile.TileSet = tmps.BottomTileSet
                                                tmpBTile.Idx = tmps.BottomTileIndex
                                                mDrawnMapTiles.Add(tmpBTile)
                                            End If

                                        End With
                                    End If
                                End If
                            End If

                        End If

                        'check that we are drawing the CentreTile
                        If tileY = DrawCentreTileY Then
                            If tileX = DrawCentreTileX Then
                                'We ARE on the Centre tile...
                                'check if we are loading
                                If Not Globals.IsLoadingTiles Then

                                    'Draw player shadow
                                    Player.DrawShadow(mode, tmpZ - 0.002F)
                                    'Draw main player character
                                    Player.DrawMain(mode, tmpZ - 0.003F)

                                    'Draw HP & MP Bars
                                    'check drawing mode
                                    If mode = Globals.DrawingMode.Normal Then
                                        'if player is still alive
                                        If Player.VitalPoints.HP > 0 Then
                                            'draw EvoLib.Protocol.VitalsBar
                                            Game.DrawVitalsBar(pos_X - CInt(MovementOffsetX), pos_Y - CInt(MovementOffsetY), Player.VitalPoints, Game.VitalsStyle.HUM_Both)
                                        End If
                                    End If
                                End If

                            End If
                        End If

                        If mode = Globals.DrawingMode.Normal Then

                            'check Top-Tile-Set is valid
                            If tmps.TopTileSet <> 255 Then
                                'check Top-Tile_Index is valid
                                If tmps.TopTileIndex <> 65535 Then
                                    'temp MirImage for this tile
                                    Dim tmpimg As MirImage = Libs.GetLib(GetImgLib(tmps.TopTileSet)).Image(tmps.TopTileIndex, , True)
                                    'If MirImage is Not empty object (IsNothing)
                                    If Not tmpimg Is Nothing Then
                                        'Use the Temp MirImage
                                        With Libs.GetLib(GetImgLib(tmps.TopTileSet)).Image(tmps.TopTileIndex)


                                            'calculate temporary Y Offset
                                            tmpOffsetY = .Header.Height - Constants.TileHeight
                                            'Draw Top Object Tile
                                            If Not Globals.IsLoadingTiles Then
                                                .Draw(pos_X, pos_Y - tmpOffsetY, tmpZ - 0.004F)
                                                Dim tmpTTile As MapTile
                                                tmpTTile.TileSet = tmps.TopTileSet
                                                tmpTTile.Idx = tmps.TopTileIndex
                                                mDrawnMapTiles.Add(tmpTTile)
                                            End If

                                        End With
                                    End If
                                End If
                            End If

                        End If


                        'Increase X Pixel-Coords and Tile-Indexes
                        pos_X += Constants.TileWidth
                        Tile_Coord_X += 1

                    Next


                    'Increase Y Pixel-Coords and Tile-Indexes
                    pos_Y += Constants.TileHeight
                    Tile_Coord_Y += 1

                Next

            End If

            'check we are rendering the proper game atm
            If Not Globals.IsLoadingTiles Then

                tc = DateTime.Now.Ticks

                'layered in order objects, right at bottom:
                'Draw Characters
                Characters.DrawCharacters(mode, offsetX, offsetY, starttilex, starttiley, 0.98F, tc)
                'Draw Mobs
                Mobs.DrawMobs(mode, offsetX, offsetY, starttilex, starttiley, 0.98F, tc)

                NPCs.DrawNPCs(mode, offsetX, offsetY, starttilex, starttiley, 0.98F, tc)

                'bottom layer:
                'Draw FloorItems
                FloorItems.Draw(mode, offsetX, offsetY, starttilex, starttiley, 0.98F)

                'middle layer:
                'Draw Magics
                Magic.DrawMagics(mode, offsetX, offsetY, starttilex, starttiley, 0.24F, tc)
                'Draw Player's top Alpha Layer (semi transparent copy of player, 
                'so we can see ourselves through Top Tiles
                Player.DrawAlpha(mode, 0.24F)

                ChatBox.DrawChatText(mode)

                'Top Layer:
                'Max Z-Order of = 0.21F
                If mode = Globals.DrawingMode.Text Then Player.DrawPlayer(mode)

            End If

        End Sub

        Public Sub DrawLightsOverlay()

            'Setup the render target for drawing the player
            DirectX.D3D.SetRenderTarget(0, DirectX.LightSurface)
            'Begin D3D scene
            DirectX.D3D.BeginScene()
            'Clear target and z-buffer
            DirectX.D3D.Clear(Microsoft.DirectX.Direct3D.ClearFlags.Target Or Microsoft.DirectX.Direct3D.ClearFlags.ZBuffer, Color.Black, 1.0F, 0)

            DirectX.GameSprite.Begin(Microsoft.DirectX.Direct3D.SpriteFlags.AlphaBlend)
            Engine.SetDrawModeLightsTex(1.0, Color.White)
            'Engine.SetDrawModeNormal(1.0F, Color.White)

            If Player.ShapeInfo.BOOL_HASLIGHT Then
                DrawLight(LightType.Torch, GameWindow.CoordX, GameWindow.CoordY)
            Else
                DrawLight(LightType.Small, GameWindow.CoordX, GameWindow.CoordY)
            End If

            For Each A As Actor.MirActor In Characters.lstCharacters

                If A.ShapeInfo.BOOL_HASLIGHT Then
                    DrawLight(LightType.Torch, A.mXCoord, A.mYCoord, A.MovementOffsetX, A.MovementOffsetY, False)
                End If

            Next

            'For idx As Integer = 466 To 471
            'With Libs.AnimationSC.Image(idx)
            '.Draw(x + 100, 0, 0.0F)
            'x += .Header.Width
            'End With
            'Next
            DirectX.GameSprite.Transform = Microsoft.DirectX.Matrix.Identity
            DirectX.GameSprite.End()

            DirectX.D3D.EndScene()

        End Sub

        Private Enum LightType
            Small = 1
            Candle = 2
            Torch = 3
        End Enum

        Private Sub DrawLight(T As LightType, X As Integer, Y As Integer, Optional offX As Integer = 0, Optional offY As Integer = 0, Optional isPlayer As Boolean = True)

            Dim oX As Integer, oY As Integer

            If (offX <> 0 And offY <> 0) Or Not isPlayer Then

                oX = ((Constants.TileWidth * (X - GameWindow.CoordX)) - offX) + GameWindow.MovementOffsetX
                oY = ((Constants.TileWidth * (Y - GameWindow.CoordY)) - offY) + GameWindow.MovementOffsetY

            Else

                oX = 0 '(Constants.TileWidth * (X - GameWindow.CoordX)) + GameWindow.MovementOffsetX
                oY = 0 '(Constants.TileWidth * (Y - GameWindow.CoordY)) + GameWindow.MovementOffsetY

            End If

            Select Case T

                Case LightType.Small
                    DirectX.GameSprite.Transform = Microsoft.DirectX.Matrix.Transformation(New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), Microsoft.DirectX.Quaternion.Identity, New Microsoft.DirectX.Vector3(0.8F, 0.8F, 1.0F), New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), Microsoft.DirectX.Quaternion.Identity, New Microsoft.DirectX.Vector3(Player.mPlayerHumAnim.PosX + (Constants.TileWidth / 2) + oX, Player.mPlayerHumAnim.PosY + (Constants.TileHeight / 2) + oY, 0.0F))

                Case LightType.Candle
                    DirectX.GameSprite.Transform = Microsoft.DirectX.Matrix.Transformation(New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), Microsoft.DirectX.Quaternion.Identity, New Microsoft.DirectX.Vector3(2.0F, 2.0F, 1.0F), New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), Microsoft.DirectX.Quaternion.Identity, New Microsoft.DirectX.Vector3(Player.mPlayerHumAnim.PosX + (Constants.TileWidth / 2) + oX, Player.mPlayerHumAnim.PosY + (Constants.TileHeight / 2) + oY, 0.0F))

                Case LightType.Torch
                    DirectX.GameSprite.Transform = Microsoft.DirectX.Matrix.Transformation(New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), Microsoft.DirectX.Quaternion.Identity, New Microsoft.DirectX.Vector3(2.2F, 2.2F, 1.0F), New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), Microsoft.DirectX.Quaternion.Identity, New Microsoft.DirectX.Vector3(Player.mPlayerHumAnim.PosX + (Constants.TileWidth / 2) + oX, Player.mPlayerHumAnim.PosY + (Constants.TileHeight / 2) + oY, 0.0F))

            End Select

            With Libs.EvoInterface.Image(37)
                .Draw(0 - .Header.OffsetX, 0 - .Header.OffsetY, 0.1F)
            End With


        End Sub

        Public Sub DrawLights()

            DirectX.D3D.BeginScene()

            DirectX.GameSprite.Begin(Microsoft.DirectX.Direct3D.SpriteFlags.AlphaBlend)
            Engine.SetDrawModeLights(1.0, Color.Black)
            DirectX.BlitD3D(DirectX.LightTexture, 0, 0, Constants.gGameResX, Constants.gGameResY, 0.23F)
            DirectX.GameSprite.End()

            DirectX.D3D.EndScene()

        End Sub

        Private Sub GameWin_InterfaceMouseEvent(ByRef type As Mouse.mMouseVars.MouseInputType, ByRef e As System.Windows.Forms.MouseEventArgs, ByRef InterfaceItem As Windows.mWindows.GUIObj) Handles GameWin.InterfaceMouseEvent
            If Left(InterfaceItem.Name, 3) = "Mob" Then
            ElseIf Left(InterfaceItem.Name, 3) = "NPC" Then
            ElseIf Left(InterfaceItem.Name, 4) = "mHum" Then
            Else
                GameWin_MouseEvent(type, e)
            End If
        End Sub

        Public Sub GameWin_MouseEvent(ByRef type As Mouse.mMouseVars.MouseInputType, ByRef e As System.Windows.Forms.MouseEventArgs, Optional ByVal mob As Boolean = False, Optional ByVal actor As Boolean = False) Handles GameWin.MouseEvent

            MousePointX = e.X
            MousePointY = e.Y

            GameWindow.HideTooltip()

            If Not MouseOverMob Then InterfaceBar.AvatarImg = -1
            If Not mob Then MouseOverMob = False : Mouse.MouseOverMobIndex = 0
            If Not actor Then Mouse.MouseOverPlayerID = 0

            Dim cx As Integer = DrawAreaStartOffsetX + (DrawCentreTileX * Constants.TileWidth) + (Constants.TileWidth / 2)
            Dim cy As Integer = DrawAreaStartOffsetY + (DrawCentreTileY * Constants.TileHeight) + (Constants.TileHeight / 2)

            Dim tilex As Integer
            Dim tiley As Integer

            Dim o As Integer
            Dim a As Integer

            tiley = (e.Y - cy) / Constants.TileHeight
            tilex = (e.X - cx) / Constants.TileWidth

            If cy > e.Y Then

                If cx > e.X Then

                    o = cx - e.X
                    a = cy - e.Y

                    MouseAngle = 360 - (Math.Atan(o / a) * (180 / Globals.PI))

                Else

                    o = e.X - cx
                    a = cy - e.Y

                    MouseAngle = (Math.Atan(o / a) * (180 / Globals.PI))

                End If

            Else

                If cx > e.X Then

                    o = cx - e.X
                    a = e.Y - cy

                    MouseAngle = 180 + (Math.Atan(o / a) * (180 / Globals.PI))

                Else

                    o = e.X - cx
                    a = e.Y - cy

                    MouseAngle = 180 - (Math.Atan(o / a) * (180 / Globals.PI))

                End If

            End If

            If MouseAngle > 337.5 Or MouseAngle <= 22.5 Then
                pointerdirection = EvoLib.Protocol.Direction.N

            ElseIf MouseAngle > 22.5 And MouseAngle <= 67.5 Then
                pointerdirection = EvoLib.Protocol.Direction.NE

            ElseIf MouseAngle > 67.5 And MouseAngle <= 112.5 Then
                pointerdirection = EvoLib.Protocol.Direction.E

            ElseIf MouseAngle > 112.5 And MouseAngle <= 157.5 Then
                pointerdirection = EvoLib.Protocol.Direction.SE

            ElseIf MouseAngle > 157.5 And MouseAngle <= 202.5 Then
                pointerdirection = EvoLib.Protocol.Direction.S

            ElseIf MouseAngle > 202.5 And MouseAngle <= 247.5 Then
                pointerdirection = EvoLib.Protocol.Direction.SW

            ElseIf MouseAngle > 247.5 And MouseAngle <= 292.5 Then
                pointerdirection = EvoLib.Protocol.Direction.W

            ElseIf MouseAngle > 292.5 And MouseAngle <= 337.5 Then
                pointerdirection = EvoLib.Protocol.Direction.NW

            End If

            MouseX = CoordX + tilex
            MouseY = CoordY + tiley

            If type = Mouse.MouseInputType.MouseDown Then

                Player.ReleaseTarget()

                If tilex = 0 And tiley = 0 And (e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right) Then

                    Player.ChangeStaticDirection(pointerdirection)
                    Player.Stand()
                    FloorItems.DoPickup()

                ElseIf e.Button = MouseButtons.Left And isShiftDown Then

                    Player.ChangeStaticDirection(pointerdirection)
                    Player.Attack()

                ElseIf e.Button = MouseButtons.Left Then

                    If GUI.MouseDragItem.HasMouseDragItem Then

                        MessageBoxes.AddMessageBox("DROP", "Drop " & GUI.MouseDragItem.MouseDragItemDesc.info.Base.STR_NAME & "?", MessageBoxes.MsgBoxButtons.YesNo, AddressOf Game.MsgBoxResultCallback)

                    Else

                        If Mobs.GetMobIDFromPos(MouseX, MouseY) > 0 Then
                            Mobs.MobMouseEvent(Mouse.MouseInputType.MouseClick, Nothing, "MON" & Mobs.GetMobIDFromPos(MouseX, MouseY))
                        Else
                            Player.ChangeStaticDirection(pointerdirection)
                            Player.Walk()
                        End If
                    End If

                ElseIf e.Button = MouseButtons.Right Then

                    Player.ChangeStaticDirection(pointerdirection)
                    Player.Run()

                End If

            ElseIf (type = Mouse.MouseInputType.MouseMove And Player.currentanim = EvoLib.Protocol.HUMAnimation.Standing) Then

                If tilex = 0 And tiley = 0 And (e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right) Then
                    Player.ChangeStaticDirection(pointerdirection)
                    Player.Stand()
                End If

            ElseIf type = Mouse.MouseInputType.MouseMove And (e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right) And Not Player.AvoidingCollision Then

                Player.ChangeStaticDirection(pointerdirection)

            ElseIf type = Mouse.MouseInputType.MouseUp Then
                Player.Stand()
            End If

            Player.ChangePointerDirection(pointerdirection)

        End Sub

        Public Sub KeyboardInput(ByRef type As Keyboard.mKeyboardVars.KeyboardInputType, ByRef e As System.Windows.Forms.KeyEventArgs)

            If type = Keyboard.KeyboardInputType.KeyDown Then

                If e.KeyCode = Keys.F1 Or e.KeyCode = Keys.F2 Or e.KeyCode = Keys.F3 Or e.KeyCode = Keys.F4 Or _
                    e.KeyCode = Keys.F5 Or e.KeyCode = Keys.F6 Or e.KeyCode = Keys.F7 Or e.KeyCode = Keys.F8 Or _
                    e.KeyCode = Keys.F9 Or e.KeyCode = Keys.F10 Or e.KeyCode = Keys.F11 Or e.KeyCode = Keys.F12 Then

                    Dim key As SkillKey

                    Select Case e.KeyCode
                        Case Keys.F1
                            key = Protocol.SkillKey.F1
                        Case Keys.F2
                            key = Protocol.SkillKey.F2
                        Case Keys.F3
                            key = Protocol.SkillKey.F3
                        Case Keys.F4
                            key = Protocol.SkillKey.F4
                        Case Keys.F5
                            key = Protocol.SkillKey.F5
                        Case Keys.F6
                            key = Protocol.SkillKey.F6
                        Case Keys.F7
                            key = Protocol.SkillKey.F7
                        Case Keys.F8
                            key = Protocol.SkillKey.F8
                        Case Keys.F9
                            key = Protocol.SkillKey.F9
                        Case Keys.F10
                            key = Protocol.SkillKey.F10
                        Case Keys.F11
                            key = Protocol.SkillKey.F11
                        Case Keys.F12
                            key = Protocol.SkillKey.F12

                    End Select

                    If MagicWindow.isSelected Then
                        'map
                        Dim p As Packet
                        p.PacketType = GamePacketType.SetSkillMapping
                        p.PacketOpCode = PacketOpCode.Notify
                        p.Username = Globals.sUsername

                        Dim struct As Protocol.PlayerSkillMapping

                        struct.BYTE_KEY = key
                        struct.BYTE_SKILL = MagicWindow.SelectedSkill
                        struct.BYTE_SET = MagicWindow.SelectedMappingsTab

                        MagicWindow.ClearSkillsList()

                        ClientSock.mSocket.SendData(MakePacket(p, struct, Globals.Crypto))

                    Else
                        'cast
                        MagicWindow.CastSpell(key)
                    End If

                ElseIf e.Shift Then
                    isShiftDown = True
                ElseIf e.Control Then
                    isControlDown = True
                ElseIf e.Alt And e.KeyCode = Keys.Enter Then
                    DirectX.ToggleFullscreen()
                End If

            ElseIf type = Keyboard.KeyboardInputType.KeyUp Then

                If e.KeyCode = Keys.ShiftKey Then
                    isShiftDown = False
                ElseIf e.KeyCode = Keys.ControlKey Then
                    isControlDown = False
                End If

            End If

        End Sub

        Public Sub KeyboardInput(ByRef type As Keyboard.mKeyboardVars.KeyboardInputType, ByRef e As System.Windows.Forms.KeyPressEventArgs)
            If type = Keyboard.KeyboardInputType.KeyPress Then
                If LCase(e.KeyChar) = "b" Then
                    ChatBox.SetModeSmall()
                ElseIf LCase(e.KeyChar) = "r" Then
                    ChatBox.SetModeLarge()
                ElseIf LCase(e.KeyChar) = "q" Then
                    Equipment.ToggleEquipmentWindow()
                ElseIf LCase(e.KeyChar) = "w" Then
                    Inventory.ToggleInventoryWindow()
                ElseIf LCase(e.KeyChar) = "m" Then
                    'Player.ToggleMount()
                ElseIf isControlDown And e.KeyChar = Chr(15) Then 'Control + O
                    Game.AskToResync()
                ElseIf e.KeyChar = Chr(27) Then
                    'Escape key
                    GameMenu.ToggleShowMenu()
                End If

                Dim beltkey As Integer

                If Int32.TryParse(LCase(e.KeyChar).ToString(), beltkey) = True Then
                    If beltkey > 0 And beltkey < 7 Then
                        Belt.UseBeltItem(beltkey)
                    End If
                End If


            End If
        End Sub

    End Module

End Namespace
